package com.wwdx.service.impl;

import com.wwdx.BaseCommons;
import com.wwdx.model.*;
import com.wwdx.model.dto.BaseActivityDTO;
import com.wwdx.model.dto.BasePayDTO;
import com.wwdx.model.dto.BaseUserInfoDTO;
import com.wwdx.service.PayServiceI;
import com.wwdx.utils.ConstantHolder;
import com.wwdx.utils.math.BigDecimalUtils;
import org.apache.commons.lang3.RandomUtils;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 支付（回调）业务处理
 * @author liguoliang
 * @date 2017-12-29
 */
@Service
public class PayServiceImpl extends BaseCommons implements PayServiceI {

    /**
     * 生成订单信息
     */
    @Override
    public BasePayDTO.PayModel save(WwdxOrderModel model, String orderno) {
        BasePayDTO.PayModel payModel = new BasePayDTO.PayModel();
        if (model == null) {
            payModel.setError("参数错误");
            return payModel;
        }
        String unionId = model.getUnionid(),productName = "",productDetail = "";
        Integer type = model.getType();
        Long productId = model.getProduct_id();
        //查询产品是否购买
        Integer isorder = wwdxOrderService.isorder(productId, unionId);
        if (isorder == 1){
            payModel.setError("已经购买此产品");
            return payModel;
        }
        //产品价格
        BigDecimal price = new BigDecimal(0);
        switch (type){
                //主题
            case ConstantHolder.Constant.THEMETYPE:
                WwdxThemeModel wwdxThemeModel = wwdxThemeService.getByThemeId(productId);
                if (wwdxThemeModel == null) {
                    payModel.setError("没有查到此商品");
                    return payModel;
                }
                productName = wwdxThemeModel.getTitle();
                productDetail = wwdxThemeModel.getContentabstract();
                price = wwdxThemeModel.getPrice();
                break;
                //书籍
            case ConstantHolder.Constant.BOOKTYPE:
                //小课
            case ConstantHolder.Constant.SMALLBOOKTYPE:
                WwdxBookModel wwdxBookModel = wwdxBookService.getByBookId(productId);
                if (wwdxBookModel == null) {
                    payModel.setError("没有查到此商品");
                    return payModel;
                }
                productName = wwdxBookModel.getBookname();
                productDetail = wwdxBookModel.getContentsummary();
                price = wwdxBookModel.getBookprice();
                break;
                //会员
            case ConstantHolder.Constant.VIPTYPE:
                WwdxVipProductModel wwdxVipProductModel = wwdxVipProductService.getByProductId(productId);
                if (wwdxVipProductModel == null) {
                    payModel.setError("没有查到此商品");
                    return payModel;
                }
                productName = "会员充值";
                productDetail = "会员充值";
                price = wwdxVipProductModel.getPrice();
                break;
            default:
                break;
        }

        //通过优惠卷购买
        price = this.purchaseCoupon(unionId,price);
        payModel.setProductPrice(price);
        payModel.setProductName(productName);
        payModel.setProductdetails(productDetail);
        payModel.setOrderno(orderno);

        model.setPrice(price);
        model.setOrderno(orderno);
        model.setCreateTime(new Date());
        model.setStatus(0);
        wwdxOrderService.save(model);
        return payModel;
    }

    /**
     * 更新订单信息
     */
    @Override
    public void payBackHandler(BasePayDTO.PayCallBackDTO dto){
        WwdxOrderModel wwdxOrderModel = wwdxOrderService.getByOrderNo(dto.getTradeNo());
        if (wwdxOrderModel == null){
            return;
        }
        Integer status = wwdxOrderModel.getStatus();
        if (status == null || status == 0){
            wwdxOrderModel.setStatus(1);
            wwdxOrderModel.setPayTime(new Date());
            wwdxOrderService.update(wwdxOrderModel);
            Integer type = wwdxOrderModel.getType();
            Long productId = wwdxOrderModel.getProduct_id();
            String unionId = wwdxOrderModel.getUnionid();
            //会员充值
            if (type == ConstantHolder.Constant.VIPTYPE){
                this.vipRecharge(unionId,productId);
            }else {
                //主题、书籍、小课购买
                taskExecutor.execute(()-> wwdxOrderService.purchase(unionId,productId,type));
            }
        }
    }

    /**
     * 会员充值
     * @param unionid 用户业务ID
     * @param productId 产品ID
     */
    @Override
    public void vipRecharge(String unionid, Long productId){
        WwdxVipProductModel wwdxVipProductModel = wwdxVipProductService.getByProductId(productId);
        WwdxVipUserModel wwdxVipUserModel = wwdxVipUserService.getByUnionId(unionid);
        Integer type = wwdxVipProductModel.getType();
        if (wwdxVipUserModel == null){
            this.saveVip(type,unionid);
        }else {
            this.updateVip(type,wwdxVipUserModel);
        }
    }

    /**
     * 续费充值
     * @param type VIP类型 {@link PayServiceImpl#plusDays(int, Object)}
     * @param model 会员信息
     */
    private void updateVip(Integer type,WwdxVipUserModel model){
        LocalDate localDate = new LocalDate();
        String expireTime = model.getExpire_time();
        int days = Days.daysBetween(new LocalDate(expireTime),localDate).getDays();
        //过期操作
        if (days > 0){
            model.setEffect_time(localDate.toString());
            localDate = this.plusDays(type, localDate);
        }else {
            localDate = this.plusDays(type, expireTime);
        }
        model.setExpire_time(localDate.toString());
        if (type == 1){
            model.setType(1);
        }
        model.setGmt_modifed(new Date());
        wwdxVipUserService.update(model);
    }

    /**
     * 首次充值
     * @param type VIP类型 {@link PayServiceImpl#plusDays(int, Object)}
     * @param unionid 用户业务ID
     */
    private void saveVip(Integer type,String unionid){
        LocalDate localDate = new LocalDate();
        LocalDate date = this.plusDays(type, localDate);
        WwdxVipUserModel wwdxVipUserModel = WwdxVipUserModel.builder()
                .effect_time(localDate.toString()).expire_time(date.toString())
                .unionid(unionid).subscribe(1).gmt_created(new Date()).gmt_modifed(new Date()).type(type == 1 ? 1 : 0).build();
        wwdxVipUserService.save(wwdxVipUserModel);
    }

    @Override
    public BigDecimal purchaseCoupon(String unionId,BigDecimal price){
        List<WwdxCouponLogModel> list = wwdxCouponLogService.list(unionId,0);
        if (!CollectionUtils.isEmpty(list)){
            //优惠卷更新
            WwdxCouponLogModel model = list.get(0);
            price = BigDecimalUtils.calculate(price).subtract(model.getPrice()).getBigDecimal();
            model.setStatus(1);
            model.setGmtModified(new Date());
            wwdxCouponLogService.update(model);
        }
        return price;
    }

    /**
     * 会员新增天数
     * @param type 会员类型
     * @param date 生效时间 类型为: {@link java.util.Date} or {@link java.lang.String}
     *
     * @return 过期时间
     */
    private LocalDate plusDays(int type,Object date){
        LocalDate localDate = new LocalDate(date);
        switch (type){
            //加一周
            case 1:
                localDate = localDate.plusWeeks(1);
                break;
            //加一月
            case 2:
                localDate = localDate.plusMonths(1);
                break;
            //加一年
            case 10:
                localDate = localDate.plusYears(1);
                break;
            //加半月
            case 4:
                localDate = localDate.plusDays(15);
                break;
            //加3天
            case 5:
                localDate = localDate.plusDays(3);
                break;
            //加5天
            case 6:
                localDate = localDate.plusDays(5);
                break;
            //加三个月
            case 8:
                localDate = localDate.plusMonths(3);
                break;
            //加半年
            case 9:
                localDate = localDate.plusMonths(6);
                break;
            default:
                break;
        }
        return localDate;
    }

    @Override
    public void executeGiveoneOrder(BaseActivityDTO.GiveOneBusinessDTO dto){
        Long bookid = dto.getBookid();
        String unionid = dto.getUnionid(),unionid2 = dto.getUnionid2(),channel = dto.getChannel(),
                key = String.format(ConstantHolder.GIVEONE_USER_LIST, unionid),appId = miDuWxService.getWxMpConfigStorage().getAppId(),
                date = new LocalDate().toString(ConstantHolder.Constant.LOCAL_DATE_PATTERN),giveUserKey = String.format(ConstantHolder.GIVEONE_STATISTICS_GIVE_CHANNEL_USER_LIST,date,channel),
                giveOneBookUserListKey = String.format(ConstantHolder.GIVEONE_STATISTICS_BOOK_USER_LIST, date, bookid),
                giveBookKey = String.format(ConstantHolder.GIVEONE_STATISTICS_GIVE_CHANNEL_BOOK_SET,date,channel);

        //分享人领取
        this.execute(bookid, unionid2, channel);
        //领取人领取
        this.execute(bookid, unionid, channel);
        //渠道下领取人数
        listOperations.leftPush(giveUserKey,unionid);
        //书籍下的领取人数
        listOperations.leftPush(giveOneBookUserListKey,unionid);
        //渠道下领取书籍数
        setOperations.add(giveBookKey,bookid.toString());
        //保存书籍领取数量
        setOperations.add(key,bookid.toString());
        //保存领取人信息
        WwdxPersonalModel wwdxPersonalModel = wwdxPersonalService.getByUnionid(unionid);
        BaseUserInfoDTO.GiveOneUserInfoDTO userInfoDTO = new BaseUserInfoDTO.GiveOneUserInfoDTO();
        userInfoDTO.setBookid(String.valueOf(bookid));
        userInfoDTO.setUnionid(unionid);
        userInfoDTO.setHeadimg(wwdxPersonalModel.getHeadImgUrl());
        userInfoDTO.setNickname(wwdxPersonalModel.getNickname());
        userInfoDTO.setIndate(new DateTime().toString(ConstantHolder.Constant.LOCAL_DATE_TIME_PATTERN));
        valueOperations.set(String.format(ConstantHolder.GIVEONE_USER_OBJ,unionid2,bookid),userInfoDTO);
        //书籍与分享人进行一一绑定
        setOperations.add(String.format(ConstantHolder.GIVEONE_USER_BOOK_SET,unionid2),String.valueOf(bookid));
        //领取人消息通知
        templateMsgTaskService.sendGiveOneTemplate(appId,unionid,unionid2,bookid);
        //分享人消息通知
        templateMsgTaskService.sendGiveOneTemplate(appId,unionid2,unionid,bookid);
    }

    private void execute(Long productId ,String unionid,String channel){
        WwdxOrderModel wwdxOrderModel = WwdxOrderModel.builder()
                .type(2).price(new BigDecimal(0)).product_id(productId).orderno(String.valueOf(RandomUtils.nextLong()))
                .createTime(new Date()).payTime(new Date()).payType(ConstantHolder.Constant.GIVEONE_PAYTYPE)
                .status(1).unionid(unionid).channel(channel).build();
        wwdxOrderService.save(wwdxOrderModel);
        //移除书架里相同的书籍
        String key = String.format(ConstantHolder.USER_BOOKSHELF_MAP,unionid);
        hashOperations.delete(key,productId.toString());
        //将已购买数据写入缓存
        taskExecutor.execute(()-> wwdxOrderService.purchase(unionid,productId,2));
    }
}